package com.springboot.lotterysystem.common.utils;


import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.springboot.lotterysystem.common.pojo.CommonResult;
import org.springframework.boot.json.JsonParseException;
import org.springframework.util.ReflectionUtils;

import java.util.List;
import java.util.concurrent.Callable;

/**
 * Created with IntelliJ IDEA.
 * Description :
 * User: jiume
 * Date: 2025-04-20
 * Time: 8:49
 */
// 本质还是使用ObjectMapper去实现序列化和反序列化
// 但由于Spring提供给我们的需要反复去实现try-catch的部分
// 因此这里我们选择对ObjectMapper重新进行封装
// 当然也可以选择在序列化和反序列化时，通过lombok提供的注解来实现try-catch
// 从而避免手动抛出异常
public class JacksonUtil {
    // 实现单例模式
    private static final ObjectMapper OBJECT_MAPPER;

    private JacksonUtil() {

    }

    static {
        OBJECT_MAPPER = new ObjectMapper();
    }

    // 参考Spring使用Jackson去实现序列化和反序列化
    private static ObjectMapper getObjectMapper() {
        return OBJECT_MAPPER;
    }

    // 序列化方法的核心
    private static  <T> T tryParse(Callable<T> parser, Class<? extends Exception> check) {
        try {
            return parser.call();
        } catch (Exception var4) {
            if (check.isAssignableFrom(var4.getClass())) {
                throw new JsonParseException(var4);
            }
            throw new IllegalStateException(var4);
        }
    }

    // 对上述方法进一步封装
    private static  <T> T tryParse(Callable<T> parser) {
       return tryParse(parser, JacksonException.class);
    }

    // 提供给外部的接口
    // 序列化方法
    public static String writeValueAsString(Object object) {
        // 本质还是使用Spring提供的ObjectMapper去实现序列化
        return JacksonUtil.tryParse(()->{
            return JacksonUtil.getObjectMapper().writeValueAsString(object);
        });
    }
    // 反序列化方法
    public static <T> T  readValue(String content, Class<T> valueType) {
        return JacksonUtil.tryParse(()->{
           return JacksonUtil.getObjectMapper().readValue(content, valueType);
        });
    }
    // 反序列化List
    // 这里的 ? 代表的是 List内部的元素类型，而原始的值我们是不知道的，因此使用通配符代替
    public static <T> T readListValue(String content, Class<?> paramClass) {
        // 先得获取 List 的类型
        JavaType javaType = JacksonUtil.getObjectMapper()
                .getTypeFactory().constructParametricType(List.class, paramClass);
        return JacksonUtil.tryParse(()->{
            return JacksonUtil.getObjectMapper().readValue(content, javaType);
        });
    }
}
